package cn.baiyang.rocketmq.spring.core;

import java.nio.charset.StandardCharsets;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;

import io.github.bucket4j.distributed.proxy.ProxyManager;

/**
 * RocketMQ Message Sender
 *
 * @author hongzhu
 * @version V1.0
 * @since 2023-07-05 18:25
 */
public abstract class AbstractRocketMQSender extends RocketMQSender {

    protected String topic;

    protected String tag;

    protected String messageGroup;

    protected AbstractRocketMQSender(String topic) {
        this.topic = topic;
    }

    protected AbstractRocketMQSender(String topic, String tag) {
        this.topic = topic;
        this.tag = tag;
    }

    protected AbstractRocketMQSender(String topic, String tag, String messageGroup) {
        this.topic = topic;
        this.tag = tag;
        this.messageGroup = messageGroup;
    }

    @Resource(name = "defaultProducer")
    @Override
    protected void setProducer(Producer producer) {
        this.producer = producer;
    }

    @Resource
    @Override
    protected void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Autowired(required = false)
    @Override
    protected void setProxyManager(ProxyManager<String> proxyManager) {
        this.proxyManager = proxyManager;
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(String body) throws ClientException {
        return send(body.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param keys key list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(String body, String... keys) throws ClientException {
        return send(body.getBytes(StandardCharsets.UTF_8), null, null, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param properties attributes list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(String body, Map<String, String> properties) throws ClientException {
        return send(body.getBytes(StandardCharsets.UTF_8), null, properties, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(String body, Long deliveryTimestamp) throws ClientException {
        return send(body.getBytes(StandardCharsets.UTF_8), deliveryTimestamp, (Map<String, String>) null, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param properties attributes list
     * @param keys key list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(String body, Map<String, String> properties, String... keys) throws ClientException {
        return send(body.getBytes(StandardCharsets.UTF_8), null, properties, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param keys key list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(String body, Long deliveryTimestamp, String... keys) throws ClientException {
        return send(body.getBytes(StandardCharsets.UTF_8), deliveryTimestamp, null, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param properties attributes list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(String body, Long deliveryTimestamp, Map<String, String> properties) throws ClientException {
        return send(body.getBytes(StandardCharsets.UTF_8), deliveryTimestamp, properties, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param properties attributes list
     * @param keys key list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(String body, Long deliveryTimestamp, Map<String, String> properties, String... keys)
        throws ClientException {
        return send(body.getBytes(StandardCharsets.UTF_8), deliveryTimestamp, properties, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(byte[] body) throws ClientException {
        return send(body, (Long) null, (Map<String, String>) null, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param keys key list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(byte[] body, String... keys) throws ClientException {
        return send(body, null, null, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param properties attributes list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(byte[] body, Map<String, String> properties) throws ClientException {
        return send(body, null, properties, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(byte[] body, Long deliveryTimestamp) throws ClientException {
        return send(body, deliveryTimestamp, (Map<String, String>) null, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param properties attributes list
     * @param keys key list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(byte[] body, Map<String, String> properties, String... keys) throws ClientException {
        return send(body, null, properties, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param keys key list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(byte[] body, Long deliveryTimestamp, String... keys) throws ClientException {
        return send(body, deliveryTimestamp, null, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param properties attributes list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(byte[] body, Long deliveryTimestamp, Map<String, String> properties) throws ClientException {
        return send(body, deliveryTimestamp, properties, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param properties attributes list
     * @param keys key list
     * @throws ClientException sending exception
     * @return Message Id String
     */
    public String send(byte[] body, Long deliveryTimestamp, Map<String, String> properties, String... keys)
        throws ClientException {
        return send(buildMessage(topic, tag, messageGroup, body, deliveryTimestamp, properties, keys));
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @return Message Id String
     */
    public String sendAsync(String body) {
        return sendAsync(body.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param keys key list
     * @return Message Id String
     */
    public String sendAsync(String body, String... keys) {
        return sendAsync(body.getBytes(StandardCharsets.UTF_8), null, null, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param properties attributes list
     * @return Message Id String
     */
    public String sendAsync(String body, Map<String, String> properties) {
        return sendAsync(body.getBytes(StandardCharsets.UTF_8), null, properties, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @return Message Id String
     */
    public String sendAsync(String body, Long deliveryTimestamp) {
        return sendAsync(body.getBytes(StandardCharsets.UTF_8), deliveryTimestamp, (Map<String, String>) null, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param properties attributes list
     * @param keys key list
     * @return Message Id String
     */
    public String sendAsync(String body, Map<String, String> properties, String... keys) {
        return sendAsync(body.getBytes(StandardCharsets.UTF_8), null, properties, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param keys key list
     * @return Message Id String
     */
    public String sendAsync(String body, Long deliveryTimestamp, String... keys) {
        return sendAsync(body.getBytes(StandardCharsets.UTF_8), deliveryTimestamp, null, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param properties attributes list
     * @return Message Id String
     */
    public String sendAsync(String body, Long deliveryTimestamp, Map<String, String> properties) {
        return sendAsync(body.getBytes(StandardCharsets.UTF_8), deliveryTimestamp, properties, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param properties attributes list
     * @param keys key list
     * @return Message Id String
     */
    public String sendAsync(String body, Long deliveryTimestamp, Map<String, String> properties, String... keys) {
        return sendAsync(body.getBytes(StandardCharsets.UTF_8), deliveryTimestamp, properties, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @return Message Id String
     */
    public String sendAsync(byte[] body) {
        return sendAsync(body, (Long) null, (Map<String, String>) null, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param keys key list
     * @return Message Id String
     */
    public String sendAsync(byte[] body, String... keys) {
        return sendAsync(body, null, null, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param properties attributes list
     * @return Message Id String
     */
    public String sendAsync(byte[] body, Map<String, String> properties) {
        return sendAsync(body, null, properties, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @return Message Id String
     */
    public String sendAsync(byte[] body, Long deliveryTimestamp) {
        return sendAsync(body, deliveryTimestamp, (Map<String, String>) null, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param properties attributes list
     * @param keys key list
     * @return Message Id String
     */
    public String sendAsync(byte[] body, Map<String, String> properties, String... keys) {
        return sendAsync(body, null, properties, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param keys key list
     * @return Message Id String
     */
    public String sendAsync(byte[] body, Long deliveryTimestamp, String... keys) {
        return sendAsync(body, deliveryTimestamp, null, keys);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param properties attributes list
     * @return Message Id String
     */
    public String sendAsync(byte[] body, Long deliveryTimestamp, Map<String, String> properties) {
        return sendAsync(body, deliveryTimestamp, properties, (String) null);
    }

    /**
     * 发送成功后返回message id
     * @param body payload
     * @param deliveryTimestamp delay time
     * @param properties attributes list
     * @param keys key list
     * @return Message Id String
     */
    public String sendAsync(byte[] body, Long deliveryTimestamp, Map<String, String> properties, String... keys) {
        return sendAsync(buildMessage(topic, tag, messageGroup, body, deliveryTimestamp, properties, keys));
    }

}
